class Snowflake {  
    private twepoch: bigint = 1288834974657n;  
    private workerIdBits: bigint = 5n;  
    private datacenterIdBits: bigint = 5n;  
    private maxWorkerId: bigint = -1n ^ (-1n << this.workerIdBits);  
    private maxDatacenterId: bigint = -1n ^ (-1n << this.datacenterIdBits);  
    private sequenceBits: bigint = 12n;  
    
    private workerIdShift: bigint = this.sequenceBits;  
    private datacenterIdShift: bigint = this.sequenceBits + this.workerIdBits;  
    private timestampLeftShift: bigint = this.sequenceBits + this.workerIdBits + this.datacenterIdBits;  
    private sequenceMask: bigint = -1n ^ (-1n << this.sequenceBits);  
    
    private lastTimestamp: bigint = -1n;  
    private sequence: bigint = 0n;  
    
    constructor(private dataCenterId: bigint, private workerId: bigint) {  
      if (dataCenterId > 31 || dataCenterId < 0) {  
        throw new Error('dataCenterId can\'t be greater than 31 or less than 0');  
      }  
      if (workerId > 31 || workerId < 0) {  
        throw new Error('workerId can\'t be greater than 31 or less than 0');  
      }  
    }  
    
    private _timeGen(): bigint {  
      return BigInt(Date.now());  
    }  
    
    private _tillNextMillis(lastTimestamp: bigint): bigint {  
      let timestamp = this._timeGen();  
      while (timestamp <= lastTimestamp) {  
        timestamp = this._timeGen();  
      }  
      return timestamp;  
    }  
    
    private _nextId(): bigint {  
      let timestamp = this._timeGen();  
    
      if (this.lastTimestamp === timestamp) {  
        this.sequence = (this.sequence + 1n) & this.sequenceMask;  
        if (this.sequence === 0n) {  
          timestamp = this._tillNextMillis(this.lastTimestamp);  
        }  
      } else {  
        this.sequence = 0n;  
      }  
    
      if (timestamp < this.lastTimestamp) {  
        throw new Error('Clock moved backwards. Refusing to generate id.');  
      }  
    
      this.lastTimestamp = timestamp;  
    
      return (  
        ((timestamp - this.twepoch) << this.timestampLeftShift) |  
        (BigInt(this.dataCenterId) << this.datacenterIdShift) |  
        (BigInt(this.workerId) << this.workerIdShift) |  
        this.sequence  
      );  
    }  
    
    nextId(): string {  
      return this._nextId().toString();  
    }  
  }  
    
  // 使用方法  
//   const snowflake = new Snowflake(1, 1);  
//   console.log(snowflake.nextId());